#include "stdafx.h"
#include "Parser.h"

#include "Analyze\Analyze.h"

Parser_MemoryManager g_Parser_MemoryManager;

Stack<CLexer_Token_Ptr> SymbolStack;
Stack<CLexer_Token_Ptr> StringStack;

// declare_type
Parser_Combinator_Node str_integer = new Parser_Str(L"integer");
Parser_Combinator_Node str_string = new Parser_Str(L"string");
Parser_Combinator_Node str_bool = new Parser_Str(L"bool");
Parser_Combinator_Node str_real = new Parser_Str(L"real");
Parser_Combinator_Node str_declare = new Parser_Str(L"declare");

// function_desc
Parser_Combinator_Node str_function = new Parser_Str(L"function");
Parser_Combinator_Node str_as = new Parser_Str(L"as");
Parser_Combinator_Node str_end = new Parser_Str(L"end");

// if_desc
Parser_Combinator_Node str_if = new Parser_Str(L"if");
Parser_Combinator_Node str_then = new Parser_Str(L"then");
Parser_Combinator_Node str_else = new Parser_Str(L"else");

// do_desc
Parser_Combinator_Node str_do = new Parser_Str(L"do");
Parser_Combinator_Node str_while = new Parser_Str(L"while");

// for_desc
Parser_Combinator_Node str_for = new Parser_Str(L"for");
Parser_Combinator_Node str_to = new Parser_Str(L"to");
Parser_Combinator_Node str_by = new Parser_Str(L"by");
Parser_Combinator_Node str_next = new Parser_Str(L"next");

// switch_desc
Parser_Combinator_Node str_switch = new Parser_Str(L"switch");
Parser_Combinator_Node str_case = new Parser_Str(L"case");
Parser_Combinator_Node str_default = new Parser_Str(L"default");

// call_desc
Parser_Combinator_Node str_call = new Parser_Str(L"call");

// operator
Parser_Combinator_Node str_point = new Parser_Str(L".");
Parser_Combinator_Node str_comma = new Parser_Str(L",");
Parser_Combinator_Node str_leftbracket = new Parser_Str(L"(");
Parser_Combinator_Node str_rightbracket = new Parser_Str(L")");
Parser_Combinator_Node str_colon_colon = new Parser_Str(L"::");
Parser_Combinator_Node str_colon = new Parser_Str(L":");
Parser_Combinator_Node str_equal = new Parser_Str(L"=");
Parser_Combinator_Node str_add = new Parser_Str(L"+");
Parser_Combinator_Node str_sub = new Parser_Str(L"-");
Parser_Combinator_Node str_mul = new Parser_Str(L"*");
Parser_Combinator_Node str_div = new Parser_Str(L"/");
Parser_Combinator_Node str_and = new Parser_Str(L"and");
Parser_Combinator_Node str_or = new Parser_Str(L"or");
Parser_Combinator_Node str_operator_and = new Parser_Str(L"&");
Parser_Combinator_Node str_operator_or = new Parser_Str(L"|");
Parser_Combinator_Node str_xor = new Parser_Str(L"^");
Parser_Combinator_Node str_mod = new Parser_Str(L"%");
Parser_Combinator_Node str_bigger = new Parser_Str(L">");
Parser_Combinator_Node str_smaller = new Parser_Str(L"<");
Parser_Combinator_Node str_bigger_equal = new Parser_Str(L">=");
Parser_Combinator_Node str_smaller_equal = new Parser_Str(L"<=");
Parser_Combinator_Node str_equal_equal = new Parser_Str(L"==");
Parser_Combinator_Node str_not_equal = new Parser_Str(L"!=");
Parser_Combinator_Node str_not = new Parser_Str(L"not");
Parser_Combinator_Node str_true = new Parser_Str(L"true");
Parser_Combinator_Node str_false = new Parser_Str(L"false");
Parser_Combinator_Node str_add_add = new Parser_Str(L"++");
Parser_Combinator_Node str_sub_sub = new Parser_Str(L"--");

// class
Parser_Combinator_Node str_class = new Parser_Str(L"class");
Parser_Combinator_Node str_inherit = new Parser_Str(L"inherit");

// property
Parser_Combinator_Node str_public = new Parser_Str(L"public");
Parser_Combinator_Node str_private = new Parser_Str(L"private");
Parser_Combinator_Node str_protected = new Parser_Str(L"protected");
Parser_Combinator_Node str_static = new Parser_Str(L"static");

// rule
Parser_Combinator_Node type_symbol = new Parser_Type(Parser_Type::ttSymbol);
Parser_Combinator_Node type_string = new Parser_Type(Parser_Type::ttString);
Parser_Combinator_Node type_number = new Parser_Type(Parser_Type::ttNumber);

// combinator
Parser_Combinator_Node program,item,stmt_list,stmt;
Parser_Combinator_Node property_desc,declare_type,declare_desc;
Parser_Combinator_Node class_desc,class_content_desc,function_desc,paramter_desc_list;
Parser_Combinator_Node if_desc,do_desc,while_desc,for_desc,switch_desc;
Parser_Combinator_Node case_list,case_desc;
Parser_Combinator_Node exp_desc,assign_desc,logic_desc,bit_desc,compare_desc;
Parser_Combinator_Node call_desc,paramter_value_list;
Parser_Combinator_Node term_desc,factor_desc,value_desc;
Parser_Combinator_Node self_desc;

CParser::CParser()
{
	// declare_type
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_integer.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_string.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_bool.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_real.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_declare.Value());

	// function_desc
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_function.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_as.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_end.Value());

	// if_desc
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_if.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_then.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_else.Value());

	// do_desc
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_do.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_while.Value());

	// for_desc
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_for.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_to.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_by.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_next.Value());

	// switch_desc
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_switch.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_case.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_default.Value());

	// call_desc
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_call.Value());

	// operator
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_point.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_comma.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_leftbracket.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_rightbracket.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_colon_colon.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_colon.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_equal.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_add.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_sub.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_mul.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_div.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_and.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_or.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_operator_and.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_operator_or.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_xor.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_mod.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_bigger.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_smaller.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_bigger_equal.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_smaller_equal.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_equal_equal.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_not_equal.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_not.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_true.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_false.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_add_add.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_sub_sub.Value());

	// class
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_class.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_inherit.Value());

	// property
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_public.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_private.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_protected.Value());
	g_Parser_MemoryManager.AddStr((Parser_Str*)str_static.Value());

	// rule
	g_Parser_MemoryManager.AddType((Parser_Type*)type_symbol.Value());
	g_Parser_MemoryManager.AddType((Parser_Type*)type_string.Value());
	g_Parser_MemoryManager.AddType((Parser_Type*)type_number.Value());

	// combinator
	program = *item;
	item = declare_desc |
			class_desc |
			function_desc;
	property_desc = str_public |
					str_private |
					str_protected;
	declare_type = str_integer[declare_type_integer] |
					str_string[declare_type_string] |
					str_bool[declare_type_bool] |
					str_real[declare_type_real] |
					type_symbol + *(str_colon_colon + type_symbol);
	paramter_desc_list = (type_symbol + str_as + declare_type)[paramter_list_desc_once] +
						*(str_comma + type_symbol + str_as + declare_type)[paramter_list_desc_more];
	paramter_value_list = exp_desc + *(str_comma + exp_desc);
	declare_desc = (str_declare + type_symbol + str_as + declare_type)[declare_desc_once] +
					*(str_comma + type_symbol + str_as + declare_type)[declare_desc_more];
	class_desc = str_class + type_symbol +
				Parser_Combinator_Node::opt(str_inherit + type_symbol +
				*(str_comma + (type_symbol & Parser_Combinator_Node::not(str_class | str_function | property_desc | str_static)))
				) + *class_content_desc + str_end + str_class;
	class_content_desc = (Parser_Combinator_Node::opt(property_desc) + Parser_Combinator_Node::opt(str_static) +
						(declare_desc | function_desc)) |
						class_desc;
	function_desc = (str_function + type_symbol)[function_desc_first] +
					(str_leftbracket + Parser_Combinator_Node::opt(paramter_desc_list) + str_rightbracket)[function_desc_second] +
					Parser_Combinator_Node::opt((str_as + declare_type)[function_desc_third]) +
					stmt_list +
					(str_end + str_function)[function_desc_fifth];
	stmt_list = *(stmt & Parser_Combinator_Node::not(str_end));
	stmt = declare_desc |
			if_desc |
			do_desc |
			while_desc |
			for_desc |
			switch_desc |
			exp_desc;
	if_desc = (str_if + exp_desc)[if_desc_first] +
			(str_then + stmt_list)[if_desc_second] +
			Parser_Combinator_Node::opt((str_else + stmt_list)[if_desc_third]) +
			(str_end + str_if)[if_desc_fourth];
	do_desc = (str_do + stmt_list)[do_desc_first] +
				(str_while + exp_desc + str_end)[do_desc_second];
	while_desc = (str_while + exp_desc)[while_desc_first] +
				(str_do + stmt_list)[while_desc_second] +
				(str_end + str_while)[while_desc_third];
	for_desc = str_for + stmt_list + str_to + exp_desc + str_by + stmt_list + str_do + stmt_list + str_next;
	switch_desc = str_switch + exp_desc + str_do + case_list + str_end + str_switch;
	case_list = *case_desc;
	case_desc = (str_case + exp_desc + str_colon + stmt_list) |
				(str_default + str_colon + stmt_list);
	assign_desc = type_symbol + str_equal + exp_desc;
	call_desc = type_symbol + *((str_point | str_colon_colon) + type_symbol) + str_leftbracket + Parser_Combinator_Node::opt(paramter_value_list) + str_rightbracket;
	logic_desc = (str_not + bit_desc)[logic_desc_first] |
				(bit_desc + *(((str_and | str_or) + bit_desc)[logic_desc_second]));
	bit_desc = compare_desc + *((str_operator_and | str_operator_or | str_xor) + compare_desc);
	compare_desc = term_desc + *((str_bigger | str_smaller |
								str_bigger_equal | str_smaller_equal |
								str_equal_equal | str_not_equal) + term_desc);
	term_desc = factor_desc + *((str_mod | str_add | str_sub) + factor_desc);
	factor_desc = self_desc + *((str_mul | str_div) + self_desc);
	self_desc = (str_add_add + type_symbol) |
				(str_sub_sub + type_symbol) |
				(type_symbol + str_add_add) |
				(type_symbol + str_sub_sub) |
				value_desc;
	value_desc = call_desc |
				assign_desc |
				Parser_Combinator_Node::clone(str_true)[value_desc_true] |
				Parser_Combinator_Node::clone(str_false)[value_desc_false] |
				(Parser_Combinator_Node::clone(type_symbol)[value_desc_symbol_first] +
				*((str_point | str_colon_colon) + type_symbol)) |
				Parser_Combinator_Node::clone(type_string)[value_desc_string] |
				Parser_Combinator_Node::clone(type_number)[value_desc_number] |
				((str_add | str_sub) + logic_desc) |
				(str_leftbracket + logic_desc + str_rightbracket);
	exp_desc = logic_desc;

	Combinator_Root = program;
}

BOOL CParser::Parser(List<NAutoPtr<CLexer_Token>>& LexerTokenList)
{
	CParser_Input input(&LexerTokenList);
	CParser_Output Result = Combinator_Root.Parser(input);
	return Result.Count() == LexerTokenList.Size();
}